﻿/*
 * SecurityDescriptor.cs
 * 
 * Microsoft Office SharePoint Server Managed Protocol Handler
 * 
 * Author: John Kozell (johnkoz@microsoft.com)
 *         Microsoft Coroporation
 * 
 * This code is an adaptation from, and interpretation of, the original SPS 2001 SDK
 * and has been updated with available information at the time of writing.
 * Not all the delcarions and alogrithms have been verified and tested
 * and there is no guarantee that they are accurate or valid, now or in the future.
 * 
 * The .NET Managed COM Interop approach contained herin was NOT created in cooperation
 * with the Microsoft SharePoint product group and has not been officially endorced
 * by Microsoft and therefore is not supported. The user of this code assumes any
 * and all risk with its use and should proceed with discression.
 * 
 * THIS CODE AND INFORMATION ARE PROVIDED AS IS WITHOUT WARRANTY OF ANY
 * KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A
 * PARTICULAR PURPOSE.
 */

using System;
using System.Collections;
using System.Runtime.InteropServices;
using System.Security.Principal;
using System.Security.AccessControl;


namespace MOSSPH
{
	public class PHSecurityDescriptor 
	{
        CommonSecurityDescriptor _csd;

        public byte[] ToBytes()
        {
            byte[] buffer = new byte[_csd.BinaryLength];
            _csd.GetBinaryForm(buffer, 0);
            return buffer;
        }

		public void LoadSecurity(string owner, string[] users)
		{
			Logging.Enter(typeof(PHSecurityDescriptor), "LoadSecurity");
			string sOperation = "Entering function";
			Logging.Trace("Creating Security Desriptor for " + owner);
			try
			{
                //SecurityIdentifier LocalAdminGroup = new SecurityIdentifier(WellKnownSidType.BuiltinAdministratorsSid, null);
                sOperation = "Getting owner SID";
                SecurityIdentifier sidOwner = GetSID(owner);
                sOperation = "Creating DACL";
                DiscretionaryAcl dacl = CreateDACL(users);

                sOperation = "Allocating security descriptor";
                _csd = new CommonSecurityDescriptor(false, false, ControlFlags.DiscretionaryAclPresent, sidOwner, null, null, dacl);
			}
			catch (Exception e)
			{
				Logging.Exception(sOperation, e);
			}
			Logging.Leave(typeof(PHSecurityDescriptor), "LoadSecurity");
		}

        private DiscretionaryAcl CreateDACL(string[] users)
		{
            DiscretionaryAcl dacl = null;
			if (users.Length > 0)
			{
                dacl = new DiscretionaryAcl(false, false, users.Length);
				foreach (string user in users)
				{
					string sOperation = null;
					try
					{
						Logging.Trace("Adding user to DACL: " + user);
						sOperation = "Creating a sid for: " + user;
                        SecurityIdentifier sid = GetSID(user);
                        if (sid != null)
                        {
                            sOperation = "Adding new ACE";
                            dacl.AddAccess(AccessControlType.Allow, sid, (int)(FileSystemRights.ReadData | FileSystemRights.ReadAttributes), InheritanceFlags.None, PropagationFlags.None);
                        }
					}
					catch (Exception e)
					{
						Logging.Exception(sOperation, e);
					}
				}
			}
            return dacl;
		}

        private SecurityIdentifier GetSID(string loginName)
        {
            SecurityIdentifier sid = null;
            try
            {
                NTAccount acct = new NTAccount(loginName);

                if (acct != null)
                    sid = (SecurityIdentifier)acct.Translate(typeof(SecurityIdentifier));
            }
            catch
            {
                Logging.Warning("SID not found for login name: " + loginName);
            }

            return sid;
        }
	}
}

